﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using System.Linq;
using OpenLightGroup.Common.LinqToVisualTree;

namespace OpenLightGroup.Common.Behaviors
{
    public class AttachDataContextBehavior : Behavior<FrameworkElement>
    {
        public AttachDataContextBehavior()
        {

        }



        #region Properties

        public string ElementName
        {
            get { return (string)GetValue(ElementNameProperty); }
            set { SetValue(ElementNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ElementName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ElementNameProperty =
            DependencyProperty.Register("ElementName", typeof(string), typeof(AttachDataContextBehavior), new PropertyMetadata(null));




        public object DataContextType
        {
            get { return (object)GetValue(DataContextTypeProperty); }
            set { SetValue(DataContextTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DataContextType.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataContextTypeProperty =
            DependencyProperty.Register("DataContextType", typeof(object), typeof(AttachDataContextBehavior), new PropertyMetadata(null));


        #endregion


        protected override void OnAttached()
        {
            base.OnAttached();

            FrameworkElement root = Application.Current.RootVisual as FrameworkElement;
            
            

            if (root != null)
            {

                if (root.Name == this.ElementName && root.DataContext != null 
                    && root.DataContext.GetType() == this.DataContextType.GetType())
                {
                    this.AssociatedObject.DataContext = root.DataContext;
                }
                else
                {

                    RecursiveSearch(root);

                }



            }

        }

        private void RecursiveSearch(FrameworkElement parentElement)
        {
            if (this.AssociatedObject.DataContext == null)
            {
                FrameworkElement currentElement = VisualTreeHelper.GetChild(parentElement, 0) as FrameworkElement;

                    int childCount = VisualTreeHelper.GetChildrenCount(parentElement);

                    for (int i = 0; i < childCount; i++)
                    {
                        FrameworkElement child = VisualTreeHelper.GetChild(currentElement, i) as FrameworkElement;

                        var element = child.FindName(this.ElementName) as FrameworkElement;

                        if (element != null && element.DataContext != null && element.DataContext.GetType() == this.DataContextType.GetType())
                        {
                            this.AssociatedObject.DataContext = element.DataContext;
                            break;
                        }
                        else
                        {
                            this.RecursiveSearch(child);


                        }

                    }

            }
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            // Insert code that you would want run when the Behavior is removed from an object.
        }


    }
}